/*
 * @Description:
 * @Author: your name
 * @version:
 * @Date: 2024-01-25 09:18:33
 * @LastEditors: your name
 * @LastEditTime: 2024-01-26 11:20:00
 */
const vetrixShader = /*glsl*/ `

`;

const fragmentShader = /*glsl*/ `uniform sampler2D colorTexture;
    uniform float rainSpeed;
    uniform float rainSize;
    varying vec2 v_textureCoordinates;
    // 从shaderToy中抄工具函数
    float rand(float x)
    {
        return fract(sin(x)*75154.32912);
    }

    float rand3d(vec3 x)
    {
        return fract(375.10297 * sin(dot(x, vec3(103.0139,227.0595,31.05914))));
    }

    float noise(float x)
    {
        float i = floor(x);
        float a = rand(i), b = rand(i+1.);
        float f = x - i;
        return mix(a,b,f);
    }

    float perlin(float x)
    {
        float r=0.,s=1.,w=1.;
        for (int i=0; i<6; i++) {
            s *= 2.0;
            w *= 0.5;
            r += w * noise(s*x);
        }
        return r;
    }

    float noise3d(vec3 x)
    {
        vec3 i = floor(x);
        float i000 = rand3d(i+vec3(0.,0.,0.)), i001 = rand3d(i+vec3(0.,0.,1.));
        float i010 = rand3d(i+vec3(0.,1.,0.)), i011 = rand3d(i+vec3(0.,1.,1.));
        float i100 = rand3d(i+vec3(1.,0.,0.)), i101 = rand3d(i+vec3(1.,0.,1.));
        float i110 = rand3d(i+vec3(1.,1.,0.)), i111 = rand3d(i+vec3(1.,1.,1.));
        vec3 f = x - i;
        return mix(mix(mix(i000,i001,f.z), mix(i010,i011,f.z), f.y),
                   mix(mix(i100,i101,f.z), mix(i110,i111,f.z), f.y), f.x);
    }

    float perlin3d(vec3 x)
    {
        float r = 0.0;
        float w = 1.0, s = 1.0;
        for (int i=0; i<5; i++) {
            w *= 0.5;
            s *= 2.0;
            r += w * noise3d(s * x);
        }
        return r;
    }

    float f(float y)
    {
        float w = 0.4; // width of strike
        return w * (perlin(2. * y) - 0.5);
    }

    float plot(vec2 p, float d, bool thicker)
    {
        if (thicker) d += 5. * abs(f(p.y + 0.001) - f(p.y));
        return smoothstep(d, 0., abs(f(p.y) - p.x));
    }
    

    float hash(float x){
        return fract(sin(x*133.3)*13.13);
    }

    void main(void){
        float time = czm_frameNumber / rainSpeed;
        // 类似于shaderToy当中的iResolution
        vec2 resolution = czm_viewport.zw;

        vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);
        vec3 c=vec3(.6,.7,.8);
        // 设置雨水密集度
        uv*=rainSize;

        float a=-.4;
        float si=sin(a),co=cos(a);
        uv*=mat2(co,-si,si,co);
        uv*=length(uv+vec2(0,4.9))*.3+1.;

        float v=1.-sin(hash(floor(uv.x*100.))*2.);
        float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;
        c*=v*b; 
        
        vec4 img=texture2D(colorTexture, v_textureCoordinates);
        gl_FragColor=img+vec4(c,1);
        // 这里需要处理一下ITime,cesium当中没有这个内置变量
        float ITime= czm_frameNumber / 120.0;
        float x = ITime + 0.1;
        float m = 0.25; // max duration of strike
        float i = floor(x/m);
        float f = x/m - i;
        float k = 0.4; // frequency of strikes
        float n = noise(i);
        float t = ceil(n-k); // occurrence
        float d = max(0., n-k) / (1.-k); // duration
        float o = ceil(t - f - (1. - d)); // occurrence with duration
        float gt = 0.2; // glare duration
        float go = ceil(t - f - (1. - gt)); // glare occurrence
        
        float lightning = 0.;
        float light = 0.;
        float glare = 0.;
        
        if (o == 1.) {
            // 这里需要重新计算uv坐标
            // 打雷
            vec2 uv2=gl_FragCoord.xy/resolution;
            uv2.x = 2. * uv2.x - 1.;
            uv2.x *= resolution.x / resolution.y;
            uv2.y += i * 2.; // select type of lightning
            float p = (noise(i+10.) - 0.5) * 2.; // position of lightning
            uv2.x -= p;

            float strike = plot(uv2, 0.01, true);
            float glow = plot(uv2, 0.04, false);
            float glow2 = plot(uv2, 1.5, false);

            lightning = strike * 0.4 + glow * 0.15;

            float h = noise(i+5.); // height
            lightning *= smoothstep(h, h+0.05, uv.y + perlin(1.2*uv.x + 4.*h)*0.03);
            lightning += glow2 * 0.3;
            light = smoothstep(5., 0., abs(uv.x - p));
            glare = go * light;
        }

        gl_FragColor+=vec4(vec3(lightning),1.);
    }`;

export default { vetrixShader, fragmentShader };
